package com.eolwral.osmonitor;

import java.text.DecimalFormat;

import com.eolwral.osmonitor.preferences.Preferences;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat;

public class OSMonitorService extends Service
{
	private static final int NOTIFYID = 20091231;
	private static int battLevel = 0;  // percentage, or -1 for unknown
	private static int temperature = 0;
	private static int useColor = 0;
	private static boolean useCelsius = true;
	private NotificationManager notificationManager = null;
	private Notification notificationBlank = null;
	private NotificationCompat.Builder notificationBuilder;

	private boolean TimeUpdate = false;
	private int UpdateInterval = 2;

	private static OSMonitorService single = null;

	public static OSMonitorService getInstance()
	{
		if(single != null)
			return single;
		return null;
	}
	
	public class OSMonitorBinder extends Binder 
	{
		OSMonitorService getService()
		{
			return OSMonitorService.this;
		}
	}
	
	private final IBinder mBinder = new OSMonitorBinder();

	private static DecimalFormat MemoryFormat = new DecimalFormat(",000");
	
	private Handler mHandler = new Handler();
	private Runnable mRefresh = new Runnable() 
	{
		private String CpuString;
		private String MemString;
		private String BatteryString;
		private String TemperatureString;
		private String CelsiusFormat;
		private String FahrenheitFormat;
		private String TopText;
		private String BottomText;

		@Override
		public void run()
		{
			if (CpuString == null)
			{
				CpuString = getResources().getString(R.string.bar_cpu);
				MemString = getResources().getString(R.string.bar_mem);
				BatteryString = getResources().getString(R.string.bar_battery);
				TemperatureString = getResources().getString(R.string.bar_temperature);
				CelsiusFormat = getResources().getString(R.string.units_temperature_celsius);
				FahrenheitFormat = getResources().getString(R.string.units_temperature_fahrenheit);
				TopText = getResources().getString(R.string.bar_topline);
				BottomText = getResources().getString(R.string.bar_bottomline);
			}

			MemStat.Update();
			ProcStat.Update();
			int cpuLoad = ProcStat.GetCPUUsageValue();
			int cpusOnline = 0;
			int color = useColor;
			
			//Set the text fields in the notification item.
			int cpuFreq = ProcStat.GetCPUScalingFreq()[0] / 1000;
			String cpuExtra = "";
			if (CpuStat.Tegra3IsTegra3())
			{
				if (CpuStat.Tegra3GetActiveCpuGroup() != null)
				{
					cpuExtra = " " + (ProcStat.Tegra3GetIsLowPowerClusterActive() ? "LP" : "G");
				}
				
				//Invert the colour if we are on the LP core.
				if (ProcStat.Tegra3GetIsLowPowerClusterActive())
				{
					color = color != 0 ? 0 : 1;
				}
			}
			for (int i: ProcStat.GetCPUScalingFreq())
			{
				if (i != 0)
				{
					++cpusOnline;
				}
			}
			String cpuStatus = String.format(CpuString, cpuLoad, cpusOnline, cpuFreq, cpuExtra);
			String memStatus = String.format(MemString, MemoryFormat.format(
					(MemStat.GetBuffers() + MemStat.GetCached() + MemStat.GetFree()) / 1024));
			String battStatus = String.format(BatteryString, battLevel);
			String tempStatus = String.format(TemperatureString, useCelsius ?
					String.format(CelsiusFormat, (float)temperature/10) :
					String.format(FahrenheitFormat, (float)temperature/10*9/5+32));

			notificationBuilder.setContentText(String.format(TopText, cpuStatus, memStatus));
			notificationBuilder.setSubText(String.format(BottomText, battStatus, tempStatus));
			Notification notification = notificationBuilder.build();
			notification.iconLevel = Math.min(cpuLoad / 10 + 2, 11) + color * 100;
			notificationManager.notify(NOTIFYID, notification);

			mHandler.postDelayed(mRefresh, UpdateInterval * 1000);
		}
	};

    @Override
    public void onCreate() {
		notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
    	InitNotification();
    	Notify();

    	single = this;
    }
    
    @Override
    public void onDestroy() {
    	Disable();
    }

    public void Notify()
    {
    	Enable();
    }
    
	
    private void Enable()
    {
    	if(!mRegistered)
    	{
    		IntentFilter filterScreenON = new IntentFilter(Intent.ACTION_SCREEN_ON);
    		registerReceiver(mReceiver, filterScreenON);

    		IntentFilter filterScreenOFF = new IntentFilter(Intent.ACTION_SCREEN_OFF);
    		registerReceiver(mReceiver, filterScreenOFF);
    		
    		mRegistered = true;
    	}
    	
		// load settings
		SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);

		try {
			UpdateInterval = Integer.parseInt(settings.getString(Preferences.PREF_UPDATE, "2"));
		} catch(Exception e) {}		
		
		if(settings.getBoolean(Preferences.PREF_CPUUSAGE, false))
		{
			if(TimeUpdate == false)
			{
				ProcStat.Update();
				mHandler.postDelayed(mRefresh, UpdateInterval * 1000);
				TimeUpdate = true;
			}
		}
		else
		{
			if(TimeUpdate == true)
			{
	    		mHandler.removeCallbacks(mRefresh);
	    		TimeUpdate = false;
			}
			notificationManager.notify(NOTIFYID, notificationBlank);
		}
		
		useCelsius = settings.getBoolean(Preferences.PREF_TEMPERATURE, true);
		useColor =  Integer.parseInt(settings.getString(Preferences.PREF_STATUSBARCOLOR, "0"));
		
		startBatteryMonitor();
    }
    
    private void Disable()
    {
		notificationManager.cancel(NOTIFYID);
    	
    	if(TimeUpdate)
    	{
    		mHandler.removeCallbacks(mRefresh);
    		TimeUpdate = false;
    	}

    	if(mRegistered)
    	{
    		unregisterReceiver(mReceiver);
    		mRegistered = false;
    	}
    	
    	stopBatteryMonitor();
    }
    
    private void startBatteryMonitor()
    {
    	IntentFilter battFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
    	registerReceiver(battReceiver, battFilter);		        		
    }
    
    private void stopBatteryMonitor()
    {
    	unregisterReceiver(battReceiver);
    }

	private static BroadcastReceiver battReceiver = new BroadcastReceiver() 
	{
		public void onReceive(Context context, Intent intent) {
			
			int rawlevel = intent.getIntExtra("level", -1);
			int scale = intent.getIntExtra("scale", -1);
			
			temperature = intent.getIntExtra("temperature", -1);

			if (rawlevel >= 0 && scale > 0) {
				battLevel = (rawlevel * 100) / scale;
			}
		}
	};

    private boolean mRegistered = false;
    private BroadcastReceiver mReceiver = new BroadcastReceiver() 
    {
    	public void onReceive(Context context, Intent intent) {
    		if(intent.getAction().equals(Intent.ACTION_SCREEN_OFF))
    		{
    	    	if(TimeUpdate)
    	    	{
    	    		mHandler.removeCallbacks(mRefresh);
    	    		TimeUpdate = false;
    	    	}
    		}
    		else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON))
    		{
    			// load settings
    			SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);

    			if(settings.getBoolean(Preferences.PREF_CPUUSAGE, false))
    			{
    				if(TimeUpdate == false)
    				{
    					mHandler.postDelayed(mRefresh, UpdateInterval * 1000);
    					TimeUpdate = true;
    				}
    			}
    		}
    	}
    }; 
     
    @Override
    public IBinder onBind(Intent intent) {
            return mBinder;
    }
	
	/**
	 * Initialises the notification icon.
	 */
	private void InitNotification() 
	{
		notificationBuilder = new NotificationCompat.Builder(this);
		notificationBuilder.setTicker(getResources().getString(R.string.app_name))
			.setContentTitle(getResources().getString(R.string.app_name))
			.setSmallIcon(R.anim.statusicon)
			.setWhen(0)
			.setOngoing(true)
			.setPriority(NotificationCompat.PRIORITY_LOW)
			.setOnlyAlertOnce(true);

		Intent notificationIntent = new Intent(this, OSMonitor.class);
		notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
		PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
		notificationBuilder.setContentIntent(contentIntent);
		notificationBlank = notificationBuilder.build();
		notificationManager.notify(NOTIFYID, notificationBlank);
	}
}
